package jwtAuth

import (
	"errors"
	"log"
	"time"
)

const DefaultInternalTime = 30 * time.Minute

type TokenCache struct {
	token        string
	generateFunc func() (string, error)
	internalTime time.Duration
}

func NewTokenCache(generateFunc func() (string, error), internalTime time.Duration) (*TokenCache, error) {
	if generateFunc == nil {
		return nil, errors.New("generateFunc is nil")
	}
	if internalTime <= 0 {
		internalTime = DefaultInternalTime
	}
	tokenCache := &TokenCache{
		generateFunc: generateFunc,
		internalTime: internalTime,
	}
	_, err := tokenCache.RefreshNewToken()
	if err != nil {
		return nil, err
	}
	go tokenCache.autoCacheToken()
	return tokenCache, nil
}

func (t *TokenCache) autoCacheToken() {
	ticker := time.NewTicker(t.internalTime)
	defer ticker.Stop()
	for {
		select {
		case <-ticker.C:
			_, err := t.RefreshNewToken()
			if err != nil {
				log.Printf("refresh new token err:%v", err)
			}
		}
	}
}

func (t *TokenCache) RefreshNewToken() (string, error) {
	if t.generateFunc == nil {
		return "", errors.New("generateFunc is nil")
	}
	token, err := t.generateFunc()
	if err != nil {
		return "", err
	}
	t.token = token
	return t.token, nil
}

func (t *TokenCache) GetToken() string {
	return t.token
}
